package application;

import io.netty.channel.Channel;
import org.apache.log4j.Logger;
import util.ReflectHelper;

import java.util.concurrent.ConcurrentHashMap;

/**
 * 请求处理总线
 * 同一请求只能由一个处理器处理，不是事件总线
 *
 * @author wyl
 */
public class RequestHandlerBus {
    private static final String SCAN_PACKAGE_NAME = "application.handlers";
    private static final Logger logger = Logger.getLogger(RequestHandlerBus.class);
    private static ConcurrentHashMap<String, RequestHandler<?, ?>> handles = new ConcurrentHashMap<>();

    //扫描请求处理器完成注册
    static {
        //在包contracts.handlers扫描继承了RequestHandler的类型，并注册此类型
        ReflectHelper.findClassByParentClass(SCAN_PACKAGE_NAME, RequestHandler.class)
                .forEach(RequestHandlerBus::registerRequestHandler);
    }


    //注册请求处理器
    public static void registerRequestHandler(RequestHandler<?, ?> handleInstance) {
        Class<?> typeArgument0 = ReflectHelper.getParentClassGenericParameter(handleInstance.getClass(), 0);
        String requestName = typeArgument0.getSimpleName();
        if (handles.containsKey(requestName)) {
            RequestHandler handler = handles.get(requestName);
            logger.warn("已经注册了" + requestName + "请求处理器:" + handler.getClass().getSimpleName());
            return;
        }
        handles.put(requestName, handleInstance);
    }

    //注册请求处理器
    public static void registerRequestHandler(Class<? extends RequestHandler> handleType) {
        try {
            registerRequestHandler(handleType.newInstance());
        } catch (Exception e) {
            logger.error("为类型" + handleType.getSimpleName() + "创建实例失败", e);
        }
    }


    //处理请求实体
    public static void handleRequest(Object requestObj, Channel ctx) {
        String requestClassName = requestObj.getClass().getSimpleName();
        RequestHandler handle = handles.get(requestClassName);
        if (handle != null) {
            handle.requestHandleCore(requestObj, ctx);
        } else {
            logger.error("没有找到到" + requestClassName + "的处理类");
        }
    }

}
